package com.jb.web.bean;

import com.jb.faces.component.NamingContainer;
import com.jb.util.ClassUtil;
import com.jb.web.context.WebContext;
import com.jb.web.model.GUID;
import com.jb.web.model.NoVisualComponent;

public class BeanFactory  {
    /**
     * Add a new component to a parent. This is a design time API.
     *
     * @param ctx Context in which this call is made.
     * @param addTo componentId to which a new component will be added.
     * @param compType class name of the new component.
     * @return true if success.
     */
    public static UIComponentImpl addNewComponent(WebContext ctx, 
                                                  String addTo, 
                                                  String compType) {
        UIComponentImpl page = (UIComponentImpl)ctx.getRequestTree();
        return addNewComponent(ctx, page, addTo, compType);
    }
    /**
     * Create a new component to a parent. 
     * @param ctx the runtime context;
     * @param root root component, usually the page of parent component.
     * @param parentId id of the parent component. If none exist, new component is
     * added to the root.
     * @param compType the class name of the component to be added.
     * @return newly created component.
     */
    public static UIComponentImpl addNewComponent(WebContext ctx, 
                                                  UIComponentImpl root,
                                                  String parentId, 
                                                  String compType) {
        
        UIComponentImpl parent = (UIComponentImpl)root.getComponentById(parentId);

        if (root.getId().equals(parentId)) {
            parent = root;
        }

        if (parent == null) {
            parent = (UIComponentImpl)root.getDescendantByClientId(parentId);
        }

        //
        //if no component found, we just add the component to the page
        //if that is not user wanted, they can delete them
        //
        if (parent == null) {
            parent = root;
        }
        return addNewComponent(ctx, parent, compType);
    }
    /**
     * Create a new component to a parent. 
     * @param ctx the runtime context.
     * @param parent the parent component.
     * @param compType the class name of the component to be added.
     * @return newly created component, null if failed to created.
     */
    public static UIComponentImpl addNewComponent(WebContext ctx, 
                                                  UIComponentImpl parent, 
                                                  String compType) {
        try {
            if (!(parent instanceof NamingContainer) || 
                !parent.isDesignable()) {
                ctx.addErrorMessage(parent, parent.getId() + " does not accept child");
                return null;
            }

            Class childClass = ClassUtil.getClass(compType);
            String newId = GUID.next(childClass);
            UIComponentImpl child = (UIComponentImpl)ClassUtil.createInstance(childClass);
            child.setId(newId);

            //we only support page level variable so if the compoent 
            //is an variable, we force to add it to the page            
            if (child instanceof NoVisualComponent) {
                parent = parent.getPage();
            }
            //set sequence before add to parent
            //as that would increase the parent max seq
            child.setSequence(parent.getMaxSeq() + 10);
            parent.addChild(child);
            child.setDefault(ctx);            
            return child;
        } catch (Throwable e) {
            ctx.addErrorMessage(parent, e.getMessage());
            return null;
        }
    }
}